/**
 * org.assess.oa.system.service.impl.TbMenuServiceImpl
 */
package org.assess.oa.system.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.assess.core.bean.node.MenuNode;
import org.assess.core.bean.node.Node;
import org.assess.core.bean.node.NodeType;
import org.assess.core.bean.node.TreeNode;
import org.assess.core.common.DateUtils;
import org.assess.core.common.GeneralUtils;
import org.assess.core.service.BaseServiceImpl;
import org.assess.core.service.ServiceResult;
import org.assess.oa.system.bean.TbMenu;
import org.assess.oa.system.bean.TbMenuItem;
import org.assess.oa.system.dao.TbMenuDAO;
import org.assess.oa.system.dao.TbMenuItemDAO;
import org.assess.oa.system.dao.TbRoleMenuDAO;
import org.assess.oa.system.dao.TbRoleMenuItemDAO;
import org.assess.oa.system.service.TbMenuService;

import com.alibaba.fastjson.JSON;

/**
 * @description 菜单管理的Service层实现类
 * @author XiaLongxiang
 * @createtime 2012-6-6 下午5:42:35
 */
public class TbMenuServiceImpl extends BaseServiceImpl implements TbMenuService {
    /** 操作菜单信息表的DAO层对象 */
    private TbMenuDAO tbMenuDAO;
    
    /** 操作菜单项信息表的DAO层对象 */
    private TbMenuItemDAO tbMenuItemDAO;
    
    /** 操作角色菜单关联信息的DAO层对象 */
    private TbRoleMenuDAO tbRoleMenuDAO;
    
    /** 操作角色菜单项关联信息的DAO层对象 */
    private TbRoleMenuItemDAO tbRoleMenuItemDAO;
    
    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(TbMenuServiceImpl.class);
    
    public TbMenu queryTbMenuById(TbMenu menu) {
        TbMenu result = null;
        try {
            result = this.tbMenuDAO.queryTbMenuById(menu.getMenu_id());
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    public TbMenuItem queryTbMenuItemById(TbMenuItem menuitem) {
        TbMenuItem result = null;
        try {
            result = this.tbMenuItemDAO.queryTbMenuItemById(menuitem.getMenuitem_id());
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    public String queryTbMenuAsList(int depth, TbMenu menu) {
        String result = "";
        try {
            Map<String, Object> parameters = new HashMap<String, Object>();
            if (menu != null && StringUtils.isNotBlank(menu.getSystem_code())) {
                if (StringUtils.isBlank(menu.getMenu_id())) {
                    parameters.put("parent_id", menu.getSystem_code());
                    parameters.put("menu_id", menu.getSystem_code());
                }
                else {
                    parameters.put("parent_id", menu.getMenu_id());
                    parameters.put("menu_id", menu.getMenu_id());
                }
                parameters.put("system_code", menu.getSystem_code());
                
                List<TbMenu> menu_records = this.tbMenuDAO.queryTbMenuAsList(parameters);
                List<TbMenuItem> menuitem_records = this.tbMenuItemDAO.queryTbMenuItemAsList(parameters);
                
                result = this.toTreePageString(depth, menu_records, menuitem_records);
            }
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    public String queryTbMenuAsJsonArray(TbMenu menu) {
        String result = "";
        try {
            Map<String, Object> parameters = new HashMap<String, Object>();
            if (menu != null) {
                parameters.put("parent_id", menu.getParent_id());
                parameters.put("system_code", menu.getSystem_code());
            }
            List<TbMenu> records = this.tbMenuDAO.queryTbMenuAsList(parameters);
            result = JSON.toJSONString(records);
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    public List<Node> queryUserMenu(String user_code, String system_code) {
        List<Node> results = null;
        try {
            Map<String, Object> parameters = new HashMap<String, Object>();
            parameters.put("user_code", user_code);
            parameters.put("system_code", system_code);
            if (!"admin".equals(user_code)) {
                parameters.put("used_flag", "1");
            }
            
            List<TbMenu> menu_records = this.tbMenuDAO.queryTbMenuAsListByUserAndSystem(parameters);
            List<TbMenuItem> mitem_records = this.tbMenuItemDAO.queryTbMenuItemAsListByUserAndSystem(parameters);
            
            results = this.toNodeList(menu_records, mitem_records, NodeType.MenuNode);
        }
        catch (Exception ex) {
            results = new ArrayList<Node>(0);
            logger.error(ex);
        }
        return results;
    }
    
    public ServiceResult saveTbMenu(TbMenu menu, boolean edit) throws Exception {
        ServiceResult result = ServiceResult.error_unknown;
        try {
            Map<String, Object> parameters = new HashMap<String, Object>();
            parameters.put("parent_id", menu.getParent_id());
            parameters.put("menu_code", menu.getMenu_code());
            List<TbMenu> records = this.tbMenuDAO.queryTbMenuAsList(parameters);
            
            if (!"1".equals(menu.getUsed_flag())) {
                menu.setUsed_flag("0");
            }
            if (StringUtils.isBlank(menu.getParent_id())) {
                menu.setParent_id(menu.getSystem_code());
            }
            
            if (edit) {
                if (records != null && !records.isEmpty()) {
                    TbMenu m = records.get(0);
                    // 如果在code和上级菜单编码相同的情况下，菜单ID和数据库中的ID不一致；
                    // 或者数据库中有多条记录，那么返回编码重复
                    if (!m.getMenu_id().equals(menu.getMenu_id()) || records.size() > 1) {
                        result = ServiceResult.save_error_code_duplicate;
                    }
                }
                
                if (result != ServiceResult.save_error_code_duplicate) {
                    menu.setModify_time(new Date());
                    menu.setModify_user(super.getLoginUserCode());
                    this.tbMenuDAO.update(menu);
                    result = ServiceResult.save_success;
                }
            }
            else if (records == null || records.isEmpty()) {
                menu.setMenu_id(GeneralUtils.getRandomId(32));
                menu.setCreate_time(new Date());
                menu.setCreate_user(super.getLoginUserCode());
                this.tbMenuDAO.insert(menu);
                result = ServiceResult.save_success;
            }
            else {
                result = ServiceResult.save_error_code_duplicate;
            }
        }
        catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
        return result;
    }
    
    public ServiceResult saveTbMenuItem(TbMenuItem menuitem, boolean edit) throws Exception {
        ServiceResult result = ServiceResult.error_unknown;
        try {
            Map<String, Object> parameters = new HashMap<String, Object>();
            parameters.put("menuitem_code", menuitem.getMenuitem_code());
            parameters.put("menu_id", menuitem.getMenu_id());
            List<TbMenuItem> records = this.tbMenuItemDAO.queryTbMenuItemAsList(parameters);
            
            if (!"1".equals(menuitem.getUsed_flag())) {
                menuitem.setUsed_flag("0");
            }
            if (edit) {
                if (records != null && !records.isEmpty()) {
                    TbMenuItem m = records.get(0);
                    if (!m.getMenuitem_id().equals(menuitem.getMenuitem_id()) || records.size() > 1) {
                        result = ServiceResult.save_error_code_duplicate;
                    }
                }
                
                if (result != ServiceResult.save_error_code_duplicate) {
                    menuitem.setModify_time(new Date());
                    menuitem.setModify_user(super.getLoginUserCode());
                    this.tbMenuItemDAO.update(menuitem);
                    result = ServiceResult.save_success;
                }
            }
            else if (records == null || records.isEmpty()) {
                menuitem.setMenuitem_id(GeneralUtils.getRandomId(32));
                menuitem.setCreate_time(new Date());
                menuitem.setCreate_user(super.getLoginUserCode());
                this.tbMenuItemDAO.insert(menuitem);
                result = ServiceResult.save_success;
            }
            else {
                result = ServiceResult.save_error_code_duplicate;
            }
        }
        catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
        return result;
    }
    
    public String checkTbMenu(TbMenu menu) {
        String result = "";
        try {
            Map<String, Object> parameters = new HashMap<String, Object>();
            parameters.put("menu_code", menu.getMenu_code());
            parameters.put("parent_id", menu.getParent_id());
            List<TbMenu> records = this.tbMenuDAO.queryTbMenuAsList(parameters);
            if (records != null && !records.isEmpty()) {
                TbMenu m = records.get(0);
                if (records.size() > 1 || !m.getMenu_id().equals(menu.getMenu_id())) {
                    result = super.toCheckExistsString(true);
                }
            }
            
            if (StringUtils.isBlank(result)) {
                result = super.toCheckExistsString(false);
            }
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    public String checkTbMenuItem(TbMenuItem menuitem) {
        String result = "";
        try {
            Map<String, Object> parameters = new HashMap<String, Object>();
            parameters.put("menuitem_code", menuitem.getMenuitem_code());
            parameters.put("menu_id", menuitem.getMenu_id());
            List<TbMenuItem> records = this.tbMenuItemDAO.queryTbMenuItemAsList(parameters);
            if (records != null && !records.isEmpty()) {
                TbMenuItem m = records.get(0);
                if (records.size() > 1 || !m.getMenuitem_id().equals(menuitem.getMenuitem_id())) {
                    result = super.toCheckExistsString(true);
                }
            }
            
            if (StringUtils.isBlank(result)) {
                result = super.toCheckExistsString(false);
            }
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    public String deleteTbMenu(TbMenu menu) throws Exception {
        String result = "";
        try {
            String[] menu_ids = menu.getMenu_id().split(",");
            for (String id : menu_ids) {
                List<TbMenu> records = this.tbMenuDAO.queryTbMenuAsListByStartProir(id);
                for (TbMenu m : records) {
                    this.tbRoleMenuItemDAO.deleteTbRoleMenuItemByMenuId(m.getMenu_id());
                    this.tbRoleMenuDAO.deleteTbRoleMenuByMenuId(m.getMenu_id());
                    this.tbMenuItemDAO.deleteTbMenuItemByMenuId(m.getMenu_id());
                    this.tbMenuDAO.deleteTbMenuById(m.getMenu_id());
                }
            }
            
            result = super.toResultString(true);
        }
        catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
        return result;
    }
    
    public String deleteTbMenuItem(TbMenuItem menuitem) throws Exception {
        String result = "";
        try {
            String[] menuitem_ids = menuitem.getMenuitem_id().split(",");
            for (String id : menuitem_ids) {
                this.tbRoleMenuItemDAO.deleteTbRoleMenuItemByMenuItemId(id);
                this.tbMenuItemDAO.deleteTbMenuItemById(id);
            }
            
            result = super.toResultString(true);
        }
        catch (Exception ex) {
            logger.error(ex);
            throw ex;
        }
        return result;
    }
    
    public String queryMenuAsRoleAll(String role_id, TbMenu menu) {
        String result = "";
        try {
            Map<String, Object> parameters = new HashMap<String, Object>();
            parameters.put("role_id", role_id);
            parameters.put("system_code", menu.getSystem_code());
            List<TbMenu> menu_records = this.tbMenuDAO.queryTbMenuAsPermissionList(parameters);
            List<TbMenuItem> mitem_records = this.tbMenuItemDAO.queryTbMenuItemAsPermissionList(parameters);
            
            List<Node> roots = this.toNodeList(menu_records, mitem_records, NodeType.TreeNode);
            result = JSON.toJSONString(roots);
        }
        catch (Exception ex) {
            logger.error(ex);
        }
        return result;
    }
    
    private List<Node> toNodeList(List<TbMenu> menu_records, List<TbMenuItem> mitem_records, NodeType nodeType) {
        List<Node> results = new ArrayList<Node>();
        Map<String, Node> mapNodes = new HashMap<String, Node>();
        if (menu_records != null && !menu_records.isEmpty()) {
            List<Node> menuNodes = new ArrayList<Node>();
            for (TbMenu m : menu_records) {
                Node node = null;
                if (nodeType == NodeType.TreeNode) {
                    node = new TreeNode();
                    node.setId(m.getMenu_id());
                    node.setName(m.getMenu_name());
                    node.setParent_id(m.getParent_id());
                    node.setType("menu");
                    ((TreeNode) node).setSystem_code(m.getSystem_code());
                    ((TreeNode) node).setOpen(true);
                    if (StringUtils.isNotBlank(m.getRole_menu_id())) {
                        ((TreeNode) node).setChecked(true);
                    }
                }
                else {
                    node = new MenuNode();
                    node.setId(m.getMenu_id());
                    node.setName(m.getMenu_name());
                    node.setType("menu");
                    node.setParent_id(m.getParent_id());
                    ((MenuNode) node).setUrl_type(m.getUrl_type());
                    ((MenuNode) node).setUrl(m.getMenu_url());
                }
                
                menuNodes.add(node);
                mapNodes.put(node.getId(), node);
                if (m.getSystem_code().equals(m.getParent_id())) {
                    results.add(node);
                }
            }
            
            for (Node node : menuNodes) {
                Node pNode = mapNodes.get(node.getParent_id());
                if (pNode != null) {
                    pNode.addNode(node);
                }
            }
        }
        
        if (mitem_records != null && !mitem_records.isEmpty()) {
            for (TbMenuItem mi : mitem_records) {
                Node pNode = mapNodes.get(mi.getMenu_id());
                if (pNode != null) {
                    Node node = null;
                    if (nodeType == NodeType.TreeNode) {
                        node = new TreeNode();
                        node.setId(mi.getMenuitem_id());
                        node.setName(mi.getMenuitem_name());
                        node.setParent_id(mi.getMenu_id());
                        node.setType("menuitem");
                        ((TreeNode) node).setNocheck(true);
                        if (StringUtils.isNotBlank(mi.getRole_menuitem_id())) {
                            ((TreeNode) node).setChecked(true);
                        }
                    }
                    else {
                        node = new MenuNode();
                        node.setId(mi.getMenuitem_id());
                        node.setName(mi.getMenuitem_name());
                        node.setParent_id(mi.getMenu_id());
                        node.setType("menuitem");
                        ((MenuNode) node).setUrl_type(mi.getUrl_type());
                        ((MenuNode) node).setUrl(mi.getMenuitem_url());
                    }
                    pNode.addNode(node);
                }
            }
        }
        
        return results;
    }
    
    private String toTreePageString(int depth, List<TbMenu> menu_records, List<TbMenuItem> menuitem_records) {
        int size = 0;
        size += menu_records != null ? menu_records.size() : 0;
        size += menuitem_records != null ? menuitem_records.size() : 0;
        StringBuffer result = new StringBuffer();
        
        result.append("{total:1,page:1,records:").append(size).append(",rows:[");
        if (menu_records != null && !menu_records.isEmpty()) {
            for (TbMenu menu : menu_records) {
                result.append(this.asTreeString(menu, depth)).append(",");
            }
        }
        if (menuitem_records != null && !menuitem_records.isEmpty()) {
            for (TbMenuItem menuitem : menuitem_records) {
                result.append(this.asTreeString(menuitem, depth)).append(",");
            }
        }
        if (size > 0) {
            result.delete(result.length() - 1, result.length());
        }
        return result.append("]}").toString();
    }
    
    private String asTreeString(TbMenu menu, int depth) {
        StringBuffer result = new StringBuffer();
        result.append("{id:\"").append(menu.getMenu_id()).append("\",cell:[");
        result.append("\"").append(menu.getMenu_code()).append("\",");
        result.append("\"").append(menu.getMenu_name()).append("\",");
        result.append("\"").append(menu.getMenu_seq()).append("\",");
        result.append("\"").append(menu.getUrl_type()).append("\",");
        result.append("\"").append(menu.getMenu_url() != null ? menu.getMenu_url() : "").append("\",");
        result.append("\"").append(menu.getUsed_flag()).append("\",");
        result.append("\"").append(menu.getCreate_time() != null ? DateUtils.getTime(menu.getCreate_time()) : "")
                .append("\",");
        result.append("\"").append(menu.getModify_time() != null ? DateUtils.getTime(menu.getModify_time()) : "")
                .append("\",");
        result.append("\"").append(depth).append("\",");
        result.append("\"").append(menu.getParent_id() != null ? menu.getParent_id() : "").append("\",");
        result.append("\"false\",");
        result.append("\"false\"");
        result.append("]}");
        return result.toString();
    }
    
    private String asTreeString(TbMenuItem menuitem, int depth) {
        StringBuffer result = new StringBuffer();
        result.append("{id:\"").append(menuitem.getMenuitem_id()).append("\",cell:[");
        result.append("\"").append(menuitem.getMenuitem_code()).append("\",");
        result.append("\"").append(menuitem.getMenuitem_name()).append("\",");
        result.append("\"").append(menuitem.getMenuitem_seq()).append("\",");
        result.append("\"").append(menuitem.getUrl_type()).append("\",");
        result.append("\"").append(menuitem.getMenuitem_url() != null ? menuitem.getMenuitem_url() : "").append("\",");
        result.append("\"").append(menuitem.getUsed_flag()).append("\",");
        result.append("\"")
                .append(menuitem.getCreate_time() != null ? DateUtils.getTime(menuitem.getCreate_time()) : "")
                .append("\",");
        result.append("\"")
                .append(menuitem.getModify_time() != null ? DateUtils.getTime(menuitem.getModify_time()) : "")
                .append("\",");
        result.append("\"").append(depth).append("\",");
        result.append("\"").append(menuitem.getMenu_id()).append("\",");
        result.append("\"true\",");
        result.append("\"false\"");
        result.append("]}");
        return result.toString();
    }
    
    public void setTbMenuDAO(TbMenuDAO tbMenuDAO) {
        this.tbMenuDAO = tbMenuDAO;
    }
    
    public void setTbMenuItemDAO(TbMenuItemDAO tbMenuItemDAO) {
        this.tbMenuItemDAO = tbMenuItemDAO;
    }
    
    public void setTbRoleMenuDAO(TbRoleMenuDAO tbRoleMenuDAO) {
        this.tbRoleMenuDAO = tbRoleMenuDAO;
    }
    
    public void setTbRoleMenuItemDAO(TbRoleMenuItemDAO tbRoleMenuItemDAO) {
        this.tbRoleMenuItemDAO = tbRoleMenuItemDAO;
    }
}
